import { Graph, Dom } from '@antv/x6'
import dagre from 'dagre'
import insertCss from 'insert-css'

insertCss(`
    @keyframes ant-line {
      to {
          stroke-dashoffset: -1000
      }
    }
`)

const INFO_FIELDS = [
  { key: 'gatewayManufacturer', label: '网关厂商' },
  { key: 'gatewayModel', label: '网关型号' },
  { key: 'gatewaySn', label: '网关Sn' },
  { key: 'lan1Speed', label: '网关Lan1口协商速率' },
  { key: 'lan2Speed', label: '网关Lan2口协商速率' },
  { key: 'lan3Speed', label: '网关Lan3口协商速率' },
  { key: 'lan4Speed', label: '网关Lan4口协商速率' },
  { key: 'routerManufacturer', label: '路由器厂商' },
  { key: 'routerModel', label: '路由器型号' },
  { key: 'routerSpeed', label: '路由器传输速率' },
  { key: 'routerChannels', label: '路由器信道数' },
  { key: 'routerCoverage', label: '路由器覆盖范围' },
  { key: 'routerAntennas', label: '路由器天线数量' },
  { key: 'stbManufacturer', label: '机顶盒厂商' },
  { key: 'stbModel', label: '机顶盒型号' },
  { key: 'stbSn', label: '机顶盒Sn' },
  { key: 'stbCpuModel', label: '机顶盒Cpu型号' },
  { key: 'stbLicense', label: '机顶盒牌照方' },
  { key: 'wirelessDeviceManufacturer', label: '无线设备厂商' },
  { key: 'wirelessDeviceModel', label: '无线设备型号' },
  { key: 'wirelessDeviceMac', label: '无线设备Mac' },
  { key: 'wirelessDeviceTraffic', label: '无线设备流量统计' }
]

// 在文件开头添加文本测量函数
function getMaxLabelWidth(fields) {
  return Math.max(
    ...fields.map((field) => {
      const textWidth = Dom.measureText(`${field.label}:`, {
        fontSize: 12,
        fontFamily: 'PingFang SC-Regular'
      }).width
      return Math.ceil(textWidth)
    })
  )
}

// 在文件开头添加计算函数
function calculateCardDimensions(firstColumnFields, secondColumnFields) {
  // 计算两列标签的最大宽度
  const firstColumnMaxWidth = getMaxLabelWidth(firstColumnFields)
  const secondColumnMaxWidth = getMaxLabelWidth(secondColumnFields)

  // 基础配置
  const leftPadding = 24
  const rightPadding = 24
  const columnGap = 48
  const labelValueGap = 12
  const valueMinWidth = 120
  const headerHeight = 40
  const headerPaddingLeft = 24
  const headerPaddingRight = 24
  const contentPaddingTop = 24
  const contentPaddingBottom = 24
  const lineHeight = 32

  // 计算值的起始位置（标签宽度 + 间距）
  const firstColumnValueX = leftPadding + firstColumnMaxWidth + labelValueGap
  const secondColumnX = firstColumnValueX + valueMinWidth + columnGap
  const secondColumnValueX = secondColumnX + secondColumnMaxWidth + labelValueGap

  // 计算总宽度
  const totalWidth = secondColumnValueX + valueMinWidth + rightPadding

  // 计算总高度 - 只考虑有值的字段
  const maxRows = Math.max(firstColumnFields.length, secondColumnFields.length)
  const contentHeight = maxRows * lineHeight
  const totalHeight = headerHeight + contentPaddingTop + contentHeight + contentPaddingBottom - 35

  return {
    width: Math.max(400, totalWidth),
    height: totalHeight,
    firstColumnValueX,
    secondColumnX,
    secondColumnValueX,
    leftPadding,
    headerPaddingLeft,
    headerPaddingRight,
    lineHeight,
    headerHeight,
    contentPaddingTop
  }
}

export default function initPage(domNode, itemClickFun, treeData) {
  //let selNodeId = null

  // 方向映射
  const dirMap = {
    LR: 'LR',
    RL: 'RL',
    TB: 'TB',
    BT: 'BT'
  }

  const colorMap = {
    white: '#ffffff', // 初始化颜色
    normal: '#F3F8FF', // 默认正常
    selected: '#CAEAFF', // 选中正常
    abnormal: '#FFF3F3', // 默认异常
    selectedAbnormal: '#FFD8D8' // 选中异常
  }

  // key前面是后端返回，冒号后是前端定义的文件名
  const deviceTypeMap = {
    网关: 'gateway',
    LAN: 'lan',
    笔记本电脑: 'note',
    路由器: 'ws',
    手机: 'phone',
    机顶盒: 'stb',
    平板电脑: 'pad'
  }

  // 获取图标
  function getIconImage(item) {
    // 特殊业务特殊处理
    if (item.deviceType === 'LAN') {
      return new URL(`../../assets/cem/lan.svg`, import.meta.url).href
    } else if (item.deviceType === 'WIFI') {
      return new URL(`../../assets/cem/wi-fi.svg`, import.meta.url).href
    }
    if (item.isRed) {
      return new URL(`../../assets/cem/${deviceTypeMap[item.deviceType]}_red.svg`, import.meta.url).href
    }
    return new URL(`../../assets/cem/${deviceTypeMap[item.deviceType]}_blue.svg`, import.meta.url).href
  }

  // // 获取图标
  // function getIconImage(item) {
  //   // 特殊业务特殊处理
  //   if (item.deviceType === 'LAN') {
  //     return require(`@/assets/cem/lan.png`)
  //   } else if (item.deviceType === 'WIFI') {
  //     return require(`@/assets/cem/wifi.png`)
  //   }
  //   if (item.isRed) {
  //     return require(`@/assets/cem/${deviceTypeMap[item.deviceType]}_red.png`)
  //   }
  //   return require(`@/assets/cem/${deviceTypeMap[item.deviceType]}_blue.png`)
  // }

  // 自定义节点
  Graph.registerNode(
    'org-node',
    {
      width: 50,
      height: 50,
      markup: [
        {
          tagName: 'rect',
          attrs: { class: 'card' }
        },
        {
          tagName: 'image',
          attrs: { class: 'image' }
        },
        {
          tagName: 'rect',
          attrs: { class: 'name-background' }
        },
        {
          tagName: 'text',
          attrs: {
            class: 'name',
            fill: '#2D3E53'
          }
        },
        {
          tagName: 'g',
          attrs: { class: 'btn-group' },
          children: [
            {
              tagName: 'rect',
              attrs: { class: 'btn' }
            },
            {
              tagName: 'path',
              attrs: { class: 'btn-sign' }
            }
          ]
        },
        {
          tagName: 'g',
          attrs: { class: 'info-card', visibility: 'hidden' },
          children: [
            {
              tagName: 'rect',
              attrs: { class: 'info-bg' }
            },
            // 左侧指向三角形
            {
              tagName: 'path',
              attrs: { class: 'pointer-triangle' }
            },
            // 卡片头部背景
            {
              tagName: 'rect',
              attrs: { class: 'header-bg' }
            },
            // 标题图标
            {
              tagName: 'image',
              attrs: { class: 'header-icon' }
            },
            // 标题文本
            {
              tagName: 'text',
              attrs: { class: 'header-title' }
            },
            // 第一列标签和值
            ...INFO_FIELDS.slice(0, Math.ceil(INFO_FIELDS.length / 2)).map((_, index) => ({
              tagName: 'text',
              attrs: {
                class: `info-label-left-${index}`,
                fontSize: 12,
                fill: '#666',
                textAnchor: 'start'
              }
            })),
            ...INFO_FIELDS.slice(0, Math.ceil(INFO_FIELDS.length / 2)).map((_, index) => ({
              tagName: 'text',
              attrs: {
                class: `info-value-left-${index}`,
                fontSize: 12,
                fill: '#333',
                textAnchor: 'start'
              }
            })),
            // 第二列标签和值
            ...INFO_FIELDS.slice(Math.ceil(INFO_FIELDS.length / 2)).map((_, index) => ({
              tagName: 'text',
              attrs: {
                class: `info-label-right-${index}`,
                fontSize: 12,
                fill: '#666',
                textAnchor: 'start'
              }
            })),
            ...INFO_FIELDS.slice(Math.ceil(INFO_FIELDS.length / 2)).map((_, index) => ({
              tagName: 'text',
              attrs: {
                class: `info-value-right-${index}`,
                fontSize: 12,
                fill: '#333',
                textAnchor: 'start'
              }
            }))
          ]
        }
      ],
      attrs: {
        '.card': {
          rx: 13,
          ry: 13,
          refWidth: '100%',
          refHeight: '100%',
          fill: colorMap.white,
          strokeWidth: 1,
          event: 'node:card',
          cursor: 'pointer'
        },
        '.image': {
          x: 6,
          y: 6,
          width: 40,
          height: 40,
          opacity: 1,
          event: 'node:image',
          cursor: 'pointer'
        },
        '.name-background': {
          refX: 0,
          refY: 55,
          width: 50,
          height: 20,
          fill: '#fff'
        },
        '.name': {
          refX: 25,
          refY: 60,
          fontFamily: 'PingFang SC-Regular',
          fontSize: 12,
          textAnchor: 'middle',
          fill: '#000'
        },
        '.btn-group': {
          refX: '50%',
          refY: '100%',
          x: 15,
          y: -5
        },
        '.btn': {
          fill: '#47CEA2',
          stroke: '#fff',
          x: -10,
          y: -10,
          height: 20,
          width: 20,
          rx: 10,
          ry: 10,
          cursor: 'pointer',
          event: 'node:collapse'
        },
        '.btn-sign': {
          refX: -5,
          refY: -5,
          stroke: '#FFFFFF',
          strokeWidth: 1.6,
          d: 'M 2 5 8 5'
        },
        '.info-card': {
          refX: '100%',
          refY: 0,
          zIndex: 999999,
          transform: 'translate(10, 0)'
        },
        '.info-bg': {
          fill: '#ffffff',
          stroke: '#e8e8e8',
          strokeWidth: 1,
          rx: 4,
          ry: 4
        },
        // 新增的样式
        '.pointer-triangle': {
          d: 'M 0,20 L -8,25 L 0,30 Z',
          fill: '#f5f5f5',
          stroke: '#e8e8e8',
          strokeWidth: 1
        },
        '.header-bg': {
          height: 32,
          fill: '#f5f5f5',
          rx: 4,
          ry: 4
        },
        '.header-icon': {
          width: 16,
          height: 16,
          x: 16,
          y: 8
        },
        '.header-title': {
          x: 40,
          y: 22,
          fontSize: 14,
          fontWeight: 600,
          fill: '#333',
          fontFamily: 'PingFang SC-Regular'
        }
      }
    },
    true
  )

  // 自定义边
  Graph.registerEdge(
    'org-edge',
    {
      zIndex: -1,
      attrs: {
        line: {
          strokeWidth: 2,
          stroke: '#A2B1C3',
          sourceMarker: null,
          targetMarker: null
        }
      }
    },
    true
  )

  // 布局方向
  const dir = dirMap.TB

  // 创建画布
  const graph = new Graph({
    width: '100%',
    height: 900,
    container: domNode,
    scroller: true,
    interacting: false,
    background: {
      color: '#fff' // 设置画布背景颜色
    },
    grid: {
      size: 10, // 网格大小 10px
      visible: true // 渲染网格背景
    },
    autoResize: true,
    panning: true, // 画布是否可以拖拽平移，默认禁用
    mousewheel: {
      enabled: true,
      modifiers: ['ctrl', 'meta'],
      zoomAtMousePosition: true,
      minScale: 0.5, // 最小缩放比例
      maxScale: 3, // 最大缩放比例
      factor: 1.2 // 缩放步长
    },
    scaling: {
      // 全局缩放限制
      min: 0.5,
      max: 3
    }
  })

  function noticeBack(node) {
    const data = node.data
    // 置灰的不可点击
    if (!data.isGray && typeof itemClickFun === 'function') {
      itemClickFun(data)
      const nodes = graph.getNodes()
      nodes.forEach((item) => {
        if (item.id !== node.id) {
          item.attr('.card', { stroke: 'none', strokeWidth: 0 })
        } else {
          item.attr('.card', { stroke: '#169BFA', strokeWidth: 1 })
        }
      })
    }
  }

  // 监听自定义事件
  function setup() {
    graph.on('node:card', ({ e, node }) => {
      e.stopPropagation()
      noticeBack(node)
    })

    graph.on('node:image', ({ e, node }) => {
      e.stopPropagation()
      noticeBack(node)
    })

    // Add hover handlers
    graph.on('node:mouseenter', ({ node }) => {
      const data = node.getData()

      node.attr('.card', {
        fill: data.isRed ? colorMap.abnormal : colorMap.normal
      })

      // 置灰的不显示信息卡片
      if (!data.isGray) {
        // 显示信息卡片
        const attrs = {
          '.info-card': {
            visibility: 'visible'
          }
        }

        // 获取有值的字段
        const validFields = INFO_FIELDS.filter((field) => data[field.key])

        // 将有值的字段平均分配到两列
        const midPoint = Math.ceil(validFields.length / 2)
        const firstColumnFields = validFields.slice(0, midPoint)
        const secondColumnFields = validFields.slice(midPoint)

        // 计算卡片尺寸和位置
        const dimensions = calculateCardDimensions(firstColumnFields, secondColumnFields)

        // 设置背景尺寸
        attrs['.info-bg'] = {
          width: dimensions.width,
          height: dimensions.height,
          fill: '#ffffff',
          stroke: '#e8e8e8',
          strokeWidth: 1,
          rx: 4,
          ry: 4
        }

        // 设置头部背景
        attrs['.header-bg'] = {
          width: dimensions.width,
          height: dimensions.headerHeight,
          fill: '#f5f5f5',
          rx: 4,
          ry: 4
        }

        // 设置标题和图标
        attrs['.header-icon'] = {
          xlinkHref: getIconImage(data),
          width: 16,
          height: 16,
          x: dimensions.headerPaddingLeft,
          y: 12
        }

        attrs['.header-title'] = {
          text: `${data.deviceType}名称：${data.name}`,
          x: dimensions.headerPaddingLeft + 24,
          y: 26
        }

        // 清除所有现有的标签和值
        INFO_FIELDS.forEach((_, index) => {
          attrs[`.info-label-left-${index}`] = { text: '' }
          attrs[`.info-value-left-${index}`] = { text: '' }
          attrs[`.info-label-right-${index}`] = { text: '' }
          attrs[`.info-value-right-${index}`] = { text: '' }
        })

        // 动态设置第一列的标签和值（只设置有值的字段）
        firstColumnFields.forEach((field, index) => {
          attrs[`.info-label-left-${index}`] = {
            text: `${field.label}:`,
            x: dimensions.leftPadding,
            y: dimensions.headerHeight + dimensions.contentPaddingTop + index * dimensions.lineHeight,
            fontSize: 12,
            fill: '#666',
            textAnchor: 'start'
          }
          attrs[`.info-value-left-${index}`] = {
            text: data[field.key],
            x: dimensions.firstColumnValueX,
            y: dimensions.headerHeight + dimensions.contentPaddingTop + index * dimensions.lineHeight,
            fontSize: 12,
            fill: '#333',
            textAnchor: 'start'
          }
        })

        // 动态设置第二列的标签和值（只设置有值的字段）
        secondColumnFields.forEach((field, index) => {
          attrs[`.info-label-right-${index}`] = {
            text: `${field.label}:`,
            x: dimensions.secondColumnX,
            y: dimensions.headerHeight + dimensions.contentPaddingTop + index * dimensions.lineHeight,
            fontSize: 12,
            fill: '#666',
            textAnchor: 'start'
          }
          attrs[`.info-value-right-${index}`] = {
            text: data[field.key],
            x: dimensions.secondColumnValueX,
            y: dimensions.headerHeight + dimensions.contentPaddingTop + index * dimensions.lineHeight,
            fontSize: 12,
            fill: '#333',
            textAnchor: 'start'
          }
        })

        node.attr(attrs)
        node.toFront()
      } else {
        node.attr('.card', {
          cursor: 'none'
        })

        node.attr('.image', {
          cursor: 'none'
        })
      }
    })

    graph.on('node:mouseleave', ({ node }) => {
      node.attr({
        '.card': {
          fill: colorMap.white
        },
        '.info-card': {
          visibility: 'hidden'
        }
      })
    })

    // Add collapse handler
    graph.on('node:collapse', ({ node }) => {
      console.log('node:collapse', node)
      const collapsed = typeof node.getData()?.collapsed === 'undefined' ? true : node.getData()?.collapsed
      // console.log('node:collapsed', collapsed)

      node.setData({ collapsed: !collapsed })

      // Update button sign
      node.attr('.btn-sign', {
        d: !collapsed ? 'M 2 5 8 5' : 'M 1 5 9 5 M 5 1 5 9',
        strokeWidth: !collapsed ? 1.8 : 1.8
      })

      // Toggle visibility of successor nodes
      const successors = graph.getSuccessors(node)
      if (successors) {
        successors.forEach((successor) => {
          successor.setVisible(!collapsed)
          const edges = graph.getConnectedEdges(successor)
          edges.forEach((edge) => edge.setVisible(!collapsed))
        })
      }

      computedPosition()
    })
  }

  function getLocation() {
    // 获取当前屏幕的像素，如果是小于1440则对半
    const nodesep = 150
    const ranksep = 80
    const screenWidth = window.innerWidth
    if (screenWidth <= 1440) {
      return {
        nodesep: nodesep / 2,
        ranksep: ranksep / 3
      }
    }
    return {
      nodesep,
      ranksep
    }
  }

  // 计算位置
  function computedPosition() {
    const nodes = graph.getNodes()
    const edges = graph.getEdges()
    const g = new dagre.graphlib.Graph()
    const { nodesep, ranksep } = getLocation()
    g.setGraph({ rankdir: dir, nodesep, ranksep })
    g.setDefaultEdgeLabel(() => ({}))

    const width = 70
    const height = 70
    nodes.forEach((node) => {
      g.setNode(node.id, { width, height })
    })

    edges.forEach((edge) => {
      const source = edge.getSource()
      const target = edge.getTarget()
      g.setEdge(source.cell, target.cell)
    })

    dagre.layout(g)

    g.nodes().forEach((id) => {
      const node = graph.getCellById(id)
      if (node) {
        const pos = g.node(id)
        node.position(pos.x, pos.y)
      }
    })

    edges.forEach((edge) => {
      const source = edge.getSourceNode()
      const target = edge.getTargetNode()

      const sourceBBox = source.getBBox()
      const targetBBox = target.getBBox()

      if ((dir === 'LR' || dir === 'RL') && sourceBBox.y !== targetBBox.y) {
        const gap = dir === 'LR' ? targetBBox.x - sourceBBox.x - sourceBBox.width : -sourceBBox.x + targetBBox.x + targetBBox.width
        const fix = dir === 'LR' ? sourceBBox.width : 0
        const x = sourceBBox.x + fix + gap / 2
        edge.setVertices([
          { x, y: sourceBBox.center.y },
          { x, y: targetBBox.center.y }
        ])
      } else if ((dir === 'TB' || dir === 'BT') && sourceBBox.x !== targetBBox.x) {
        const gap = dir === 'TB' ? targetBBox.y - sourceBBox.y - sourceBBox.height : -sourceBBox.y + targetBBox.y + targetBBox.height
        const fix = dir === 'TB' ? sourceBBox.height : 0
        const y = sourceBBox.y + fix + gap / 2
        edge.setVertices([
          { x: sourceBBox.center.x, y },
          { x: targetBBox.center.x, y }
        ])
      } else {
        edge.setVertices([])
      }
    })
  }

  function createNode(item, image) {
    let btnGroup = {}
    if (item.children && item.children.length > 0) {
      btnGroup = (() => {
        switch (dir) {
          case 'TB':
            return { refX: '50%', refY: '100%', x: 15, y: -5 }
          case 'BT':
            return { refX: '50%', refY: 0, x: -15, y: -15 }
          case 'LR':
            return { refX: '100%', refY: '50%', x: -5, y: -10 }
          case 'RL':
            return { refX: 0, refY: '50%', x: -25, y: -10 }
          default:
            return { refX: '100%', refY: '50%', x: -10, y: -10 }
        }
      })()
    } else {
      btnGroup.display = 'none'
    }

    // 是否可折叠
    if (item.collapsible) {
      btnGroup.display = 'block'
    } else {
      btnGroup.display = 'none'
    }
    // isRed; // 设备是否异常 变红:true 不变红:false
    return graph.createNode({
      id: item.id,
      data: item,
      shape: 'org-node',
      attrs: {
        '.card': {},
        '.image': { xlinkHref: image },
        '.name-background': {
          width: 70,
          height: item.connectionType === 'solid' ? 20 : 35
        },
        '.name': {
          text:
            item.connectionType === 'solid'
              ? Dom.breakText(item.deviceType, { width: 70, height: 45 })
              : Dom.breakText(`${item.deviceType}\n${item.name}`, { width: 70, height: 45 })
        },
        // 默认隐藏按钮组
        '.btn-group': btnGroup
      }
    })
  }

  function createEdge(source, target, item) {
    return graph.createEdge({
      shape: 'org-edge',
      source: { cell: source.id },
      target: { cell: target.id },
      attrs: {
        line:
          item.connectionType === 'dashed'
            ? {
                stroke: '#1890ff',
                strokeDasharray: 5
                // style: {
                //   animation: 'ant-line 30s infinite linear',
                // },
              }
            : {}
      }
    })
  }

  // 树转数组
  function treeToArray(tree) {
    const arr = []
    tree.forEach((item) => {
      arr.push(item)
      if (item.children) {
        arr.push(...treeToArray(item.children))
      }
    })
    return arr
  }

  const nodes = []
  const edges = []

  const list = treeToArray(treeData)

  for (const item of list) {
    const node = createNode(item, getIconImage(item))
    nodes.push(node)
    if (item.children && item.children.length > 0) {
      for (const child of item.children) {
        const edge = createEdge(node, createNode(child, getIconImage(child)), child)
        edges.push(edge)
      }
    }
  }

  graph.resetCells([...nodes, ...edges])

  computedPosition()
  setup()

  // 新增居中逻辑
  graph.centerContent({
    padding: { left: 100, right: 100 },
    animation: true
  })
}
